﻿/*
	Copyright (C) 2019 Zongming Liu <1849059316@qq.com>

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.
	
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.
	
	You should have received a copy of the GNU General Public License along
	with this program; if not, write to the Free Software Foundation, Inc.,
	51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include "ActionManager.h"
#include "../base/Debuger.h"
#include "Action.h"
#include "IActableObject.h"
#include <vector>
#include <list>


namespace SkyEngine2d
{
	//节点的动画信息 结构
	struct ActionElement
	{
		struct actionInfo
		{
			ActionSharedPtr actionPtr;//保存动画的指针
			bool            isRemoved;//标记是否被删除 
			actionInfo(ActionSharedPtr ptr)
				:actionPtr(ptr), isRemoved(false){}
			~actionInfo() {}
		};
		//目标节点的全部动画
		std::list<std::unique_ptr<actionInfo>> actions;
		IActableObject* target;
		//当前节点是否被暂停    
		bool	paused;
	
		ActionElement()
			:paused(false)
			 {}
		~ActionElement() {}
	};
	
	
	
	ActionManager::ActionManager()
		:m_allRemoved(false)
		,m_currActionElement(nullptr)
	{
	
	}
	
	ActionManager::~ActionManager()
	{
	
	}
	
	bool ActionManager::addAction(ActionSharedPtr action, IActableObject* target, bool suspend /*= false*/)
	{
		DebugerAssert(action != nullptr, "ActionManager::addAction  arg action is null ");
		DebugerAssert(target != nullptr, "ActionManager::addAction  arg target is null ");
		if (action == nullptr || target == nullptr)
		{
			return false;
		}
	
		Action * ac = action.get();
		bool b = ac->startWithTarget(target);
		if (!b)
		{
			return false;
		}
	
		//先试试能不能找到这个Traget
		auto & f = m_actionTable.find(target);
		if (f != m_actionTable.end())
		{  //存在这个节点
			f->second->actions.push_front(std::make_unique<ActionElement::actionInfo>(action));
		}
		else
		{
			auto e = std::make_unique<ActionElement>();
			e->paused = false;
			e->target = target;
			auto p = std::make_unique<ActionElement::actionInfo>(action);
			suspend ? action->suspend() : action->resume();
			e->actions.push_front(std::move(p));
			m_actionTable.emplace(target, std::move(e));
		}
	
		return true;
	}
	
	
	void ActionManager::suspendActionOfTarget(const IActableObject * target)
	{
		auto f = m_actionTable.find(target);
		if (f!=m_actionTable.end())
		{
			f->second->paused = true;
		}
	}
	
	void ActionManager::resumeActionOfTarget(const IActableObject * target)
	{
		auto f = m_actionTable.find(target);
		if (f != m_actionTable.end())
		{
			f->second->paused = false;
		}
	}
	
	void ActionManager::suspendAction(const IActableObject * target, const std::wstring & name)
	{
		auto f = m_actionTable.find(target);
		if (f != m_actionTable.end())
		{
			for (auto & p : f->second->actions)
			{
				if (p->actionPtr->getName()==name)
				{
					p->actionPtr->suspend();
					return;
				}
			}
		}
	}
	
	void ActionManager::resumeAction(const IActableObject * target, const std::wstring & name)
	{
		auto f = m_actionTable.find(target);
		if (f != m_actionTable.end())
		{
			for (auto & p : f->second->actions)
			{
				if (p->actionPtr->getName() == name)
				{
					p->actionPtr->resume();
					return;
				}
			}
		}
	}
	
	void ActionManager::removeAllActions()
	{
		m_allRemoved = true;
	}
	
	void ActionManager::removeAllActionsOfTarget(const IActableObject * target)
	{
		DebugerAssert(target != nullptr, "ActionManager::removeAllActionsOfTarget arg is null ");
	
		if (target == nullptr)
		{
			return;
		}
	
		auto & f = m_actionTable.find(target);
		if (f != m_actionTable.end())
		{
			m_removedNode.push_back(target);
		}
	}
	
	
	void ActionManager::removeActionByName(const std::wstring & name, const IActableObject * target)
	{
		//先找目标节点  
		auto & f = m_actionTable.find(target);
		if (f!=m_actionTable.end())
		{
			for (auto & v :f->second->actions)
			{
				if (v->actionPtr->getName()==name)
				{
					v->isRemoved = true;
				}
			}
		}
	}
	
	std::shared_ptr<Action> ActionManager::getActionByName(const std::wstring & name, const IActableObject * target)
	{
		//先找目标节点  
		auto & f = m_actionTable.find(target);
		if (f != m_actionTable.end())
		{
			for (const auto & v :f->second->actions)
			{
				if (v->actionPtr->getName()==name)
				{
					return v->actionPtr;
				}
			}
		}
	
		return nullptr;
	}
	
	void ActionManager::update(float dt)
	{
		//删除全部动画
		if (m_allRemoved)
		{
			m_actionTable.clear();
		}
		//删除节点的动画 
		for (auto node : m_removedNode)
		{
			m_actionTable.erase(node);
		}
		m_removedNode.clear();
	
		//遍历整个动画表  
		auto ementIter = m_actionTable.begin();
		auto ementEnd = m_actionTable.end();
		for (;ementIter!=ementEnd; ++ementIter) 
		{
			m_currActionElement = ementIter->second.get();
			if (!m_currActionElement->paused)
			{  //如果没有被暂停  
	
				//遍历这个节点的全部动画
				auto & actionArr = m_currActionElement->actions;
				auto actionIt = actionArr.begin();
				auto actionEnd = actionArr.end();
				for (;actionIt!=actionEnd;)
				{
					auto & it = *actionIt;
					if (!it->isRemoved)
					{
						if (it->actionPtr->isSuspend())
						{
							continue;
						}
	
						ActionSharedPtr  action = it->actionPtr;
						DebugerAssert(action != nullptr, "动画为 null ");
						action->step(dt);
						if (action->isDone()) //如果这个动画播放完毕了 
						{	
							action->stop();
							actionIt = actionArr.erase(actionIt);  //移除这个动画
						}
						else
						{
							++ actionIt;
						}
					}
					else
					{
						actionIt = actionArr.erase(actionIt);  //移除这个动画
					}
				}
			}
		}
	
	
	}
	
}
